package s;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.imageio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.semanticmetadata.lire.DocumentBuilder;
import net.semanticmetadata.lire.DocumentBuilderFactory;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;

import com.mysql.jdbc.Statement;

import cbir.ScaleJPG;
import cbir.Thumb;
import cbir.md5;


@SuppressWarnings("deprecation")
public class Upload extends HttpServlet{
	
		private static final long serialVersionUID = -6642198667458873473L;
		private static final String alphaNumeric = "abcdefghijklmnopqrstuvwxyz_1234567890";
		
		private Properties props;
		private String propsPath;
	
		public void init(ServletConfig config) throws ServletException {
				super.init(config);
		}
		
		
		protected void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {}
		
		protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
			exe(req,res);
		}
			
	
	
	private synchronized void exe(HttpServletRequest req, HttpServletResponse res) throws IOException {

				//		PROPERTIES
			this.propsPath = this.getServletContext().getRealPath("/");
			this.props = new Properties();
			try {
				props.loadFromXML(new FileInputStream(propsPath + "properties.properties"));
			} catch (FileNotFoundException e) {e.printStackTrace();} 
			catch (IOException e) {e.printStackTrace();}

				FileItem item = null;
				FileItem fileToBeSaved = null;
				String filename = new String();

				/* **  Img receiving  ** */
				if(ServletFileUpload.isMultipartContent(req)) {
					FileItemFactory factory = new DiskFileItemFactory();
					ServletFileUpload upload = new ServletFileUpload(factory);
		
					List<?> items = null;
					try {
						items = upload.parseRequest(req);
					} catch (FileUploadException e) {e.printStackTrace();}

					Iterator<?> iter = items.iterator();
					while (iter.hasNext()) {
					    item = (FileItem) iter.next();
					    if (item.isFormField()) {} 
					    else {
//					    	System.out.println("size: " +item.getSize());
					    	filename = item.getName();
					        fileToBeSaved = item;
					    }
					}
				}else{
					PrintWriter out =  res.getWriter();
					out.print("FAIL");
					out.close();
					return;
				}
								
				/* **  Does filename already exists? ** */
				Connection connection = null;
				Statement statement = null;
				boolean exit = false;
				
				String originalFilename = filename;
				
				while(exit == false){
						try {
							Class.forName("com.mysql.jdbc.Driver");
							connection = DriverManager.getConnection(props.getProperty("DB_URL"), props.getProperty("DB_USER"), props.getProperty("DB_PASS"));
							statement = (Statement) connection.createStatement();
							ResultSet rs = statement.executeQuery("SELECT count(*) as num FROM img WHERE Filename = '"+filename+"';");
							if(rs.next()){
									if(rs.getInt("num") == 0)
											exit = true;
									else{	// ..renaming file
											String ext = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
											String mod = Character.toString(alphaNumeric.charAt( (int)(Math.random()*alphaNumeric.length()))) + Character.toString(alphaNumeric.charAt( (int)(Math.random()*alphaNumeric.length()))) + Character.toString(alphaNumeric.charAt( (int)(Math.random()*alphaNumeric.length())));
											filename = originalFilename.substring(0, originalFilename.lastIndexOf(".")) + mod + ext;
									}
							}
						} catch (SQLException e) {e.printStackTrace();} catch (ClassNotFoundException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
				}
				
				/* **  Writing the file  ** */
				File uploadedFile = new File( this.getServletContext().getRealPath("/") + props.getProperty("IMG_PATH") + filename);
			    try {
					fileToBeSaved.write(uploadedFile);	// writing
				} catch (Exception e) {e.printStackTrace();}
				
				
				/* **  Hash computing  ** */
				String hash = null;
				try {
						hash = md5.calcola(uploadedFile);
						ResultSet rs = statement.executeQuery("SELECT Filename FROM img WHERE Hash = '" + hash + "';");
						
						if(rs.next()){						
								// Removing the file
								if(uploadedFile.delete() == false){
										PrintWriter o =  res.getWriter();
										o.print("FAIL");
								}else{
										PrintWriter o =  res.getWriter();
										o.print("OK");
								}
								
								connection.close();
								return;
						}else{	// hash doesn't already exists							
							/* **  Thumb  ** */
							String thumbname = Thumb.getThumb(filename);
							ScaleJPG.scale( this.getServletContext().getRealPath("/") + props.getProperty("IMG_PATH"), this.getServletContext().getRealPath("/") + props.getProperty("IMG_PATH") + "thumb/", filename, thumbname);
							
							/* **  Indexing ** */
							IndexWriter iw = null;
														
							if(props.getProperty("IS_CLEAN").compareTo("true") == 0){
								props.setProperty("IS_CLEAN", "false");
								props.storeToXML(new FileOutputStream(new File(propsPath + "properties.properties")), "CBIR_properties");
								iw = new IndexWriter( this.getServletContext().getRealPath("/") + props.getProperty("INDEX_PATH"), new SimpleAnalyzer(), true);
							}
							else{
								iw = new IndexWriter( this.getServletContext().getRealPath("/") + props.getProperty("INDEX_PATH"), new SimpleAnalyzer(), false);
							}
							
							DocumentBuilder builder = DocumentBuilderFactory.getExtensiveDocumentBuilder();
							Document doc = builder.createDocument( new FileInputStream( this.getServletContext().getRealPath("/") + props.getProperty("IMG_PATH") + "thumb/" + thumbname), thumbname);							
							iw.addDocument(doc);
							iw.close();
							
							/* **  Inserting in the mysql DB ** */
							BufferedImage bi = ImageIO.read(uploadedFile);
							statement.executeUpdate("INSERT INTO img (Filename, Height, Width, Hash) VALUES('"+filename+"', '" + 
									bi.getHeight() + "', '" + bi.getWidth() +"', '" + hash +"');");
							connection.close();

							PrintWriter o =  res.getWriter();
							o.print("OK");
						}
					
				} catch (SQLException sqle) {sqle.printStackTrace();}
				catch (NoSuchAlgorithmException nsae) {nsae.printStackTrace();}
	}		
}